#pragma once

#include <zenoui/Widget.hpp>
#include <zenoui/widgets/EmptyWidget.hpp>
#include <zenoui/Property.hpp>
#include <zenox/pragma.hpp>
#include <functional>
#include <string>
#include <vector>

namespace zenoui {

struct FontData;

struct LabelWidget : EmptyWidget {
protected:
    std::u32string m_text;
    TextAlignment m_alignment = TextAlignCenter;
    glm::vec4 m_font_color{0.9f, 0.8f, 0.7f, 1.0f};
    std::string m_font_name = "default";
    float m_font_size = 32.0f;
    mutable Rect m_cached_text_rect{}; // cachemask=1
    mutable std::vector<std::vector<float>> m_cached_scanxy{}; // cachemask=2
    mutable std::vector<size_t> m_cached_newlines{}; // cachemask=4
    mutable std::function<void(float, float)> m_cached_drawcall{}; // cachemask=8
    mutable FontData *m_cached_font_data{}; // cachemask=16
    mutable int m_cache_valid_mask = 0;

    using EmptyWidget::property; // inherits all existing properties from EmptyWidget
    void property(FontNameProperty *prop) override; // text font (std::string, see FontData.cpp for a complete list)
    void property(FontSizeProperty *prop) override; // font size (float) in height
    void property(FontColorProperty *prop) override; // text color (glm::vec4, RGBA)
    void property(TextAlignmentProperty *prop) override; // text alignment (TextAlignment)
    void property(TextProperty *prop) override; // text content (std::u32string)
    void paint() override; // paint the text + background fill
    void do_invalidate_text_cache(int mask = 31); // must be called whenever m_text or m_font_* has been changed (this clears the m_cache_valid_mask)
    void do_require_text_cache(int mask = 31) const; // called when internal function need m_cached_* variables

public:
    void label_paint(); // paint the text only, no background
    Rect label_rect() const; // predict the bounding rect where text will occupy
    float label_query_index(glm::vec2 mpos) const; // predict which character the mouse position is on
    glm::vec2 label_index_char_rel_xy(size_t index) const; // reverse function of label_query_index: find relative X of a character

    LabelWidget();
    ~LabelWidget();
};

}
